﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;

namespace SpaceWolf.GameLogic
{
    public class Space_Object
    {
        #region Variables
        protected string sName;
        protected ObjectState objectState;
        protected Vector3 location;
        protected Matrix orientation = Matrix.Identity;
        protected BoundingSphere _boundSphere;
        protected Vector3 rotations;

        protected Vector3 direction = Vector3.Forward;
        protected Vector3 right;
        protected Vector3 up = Vector3.Up;

        protected Vector3 force;
        protected float energy;

        protected ObjectTypes type;

        protected bool isHit;
        protected float hitTimeoutMs = -1;
        /// <summary>
        /// Time for the explosion effect.
        /// </summary>
        protected const int MaxHitTimeoutMs = 1000;

        #endregion
        
        public String Name
        {
            get
            {
                return this.sName;
            }
        }
        /// <summary>
        /// Ship Up vector
        /// </summary>
        public Vector3 Up
        {
            get
            {
                return up;
            }
        }
        /// <summary>
        /// Ship right vector
        /// </summary>
        public Vector3 Right
        {
            get
            {
                return right;
            }
        }

        /// <summary>
        /// Ship direction/forward
        /// </summary>
        public Vector3 Direction
        {
            set
            {
                direction = value;
            }
            get
            {
                return this.direction;
            }
        }


        public bool Hit
        {
            get
            {
                return this.isHit;
            }
        }

        public ObjectTypes Type
        {
            set
            {
                this.type = value;
            }
            get 
            {
                return this.type;
            }
        }

        public BoundingSphere boundSphere
        {
            set
            {
                this._boundSphere = value;
            }
            get
            {
                return this._boundSphere;
            }
        }

        /// <summary>
        /// XYZ rotations in space
        /// </summary>
        public Vector3 Rotations
        {
            set
            {
                this.rotations = value;
            }
            get
            {
                return this.rotations;
            }
        }

        public float Energy
        {
            set
            {
                this.energy = value;
            }
            get
            {
                return this.energy;
            }
        }

        public Matrix Orientation
        {
            set
            {
                this.orientation = value;
            }
            get
            {
                return this.orientation;
            }
        }

        public ObjectState State
        {
            set
            {
                this.objectState = value;
            }
            get
            {
                return this.objectState;
            }
        }

        /// <summary>
        /// Location of Object
        /// </summary>
        public Vector3 Location
        {
            set
            {
                this.location = value;
            }
            get
            {
                return this.location;
            }
        }

        public Space_Object()
        {
        }

        public Space_Object(ObjectTypes type, Vector3 position, Matrix Orientation, Vector3 rotations)
        {
            this.type = type;
            this.location = position;
            this.rotations = rotations;
            this.orientation = Orientation;
        }

        public Space_Object(ObjectTypes type,string Name, Vector3 position, Matrix Orientation, Vector3 rotations)
        {
            this.type = type;
            this.location = position;
            this.rotations = rotations;
            this.orientation = Orientation;
            this.sName = Name;
        }
        /// <summary>
        /// Update object camera & Orientation
        /// </summary>
        public virtual void Update()
        {
            direction = Vector3.Transform(Vector3.Backward, orientation);
            direction.Normalize();

            right = Vector3.Cross(up, direction);
            Vector3.Normalize(right);

            Quaternion qyaw = Quaternion.CreateFromAxisAngle(up, (float)rotations.X);
            qyaw.Normalize();
            Quaternion qtilt = Quaternion.CreateFromAxisAngle(right, (float)rotations.Y);
            qtilt.Normalize();
            Quaternion qroll = Quaternion.CreateFromAxisAngle(direction, (float)rotations.Z);
            qroll.Normalize();
            Quaternion yawpitch = qyaw * qtilt * qroll;
            yawpitch.Normalize();

            up = Vector3.Transform(up, yawpitch);

            orientation *= Matrix.CreateFromQuaternion(yawpitch);

            float moveFactor = 0.009f;

            force = direction * moveFactor;

            _boundSphere.Center = this.location;

            if (isHit)
            {
                if (hitTimeoutMs < 0)
                    hitTimeoutMs = MaxHitTimeoutMs;
            }

            if (hitTimeoutMs >= 0)
            {
                hitTimeoutMs -= BaseGame.ElapsedTimeThisFrameInMilliseconds;
                if (hitTimeoutMs < 0)
                {
                    isHit = false;
                    hitTimeoutMs = -1;
                }
            } // if (explosionTimeoutMs)
        }

        public virtual void Impact(Space_Object otherShip)
        {
            Vector3 impact = otherShip.force - force;
            Vector3 impulse = Vector3.Normalize(otherShip.location - location);
            float impactSpeed = Vector3.Dot(impact, impulse);
            impactSpeed = -Math.Abs(impactSpeed);
            impulse *= impactSpeed;
            //otherShip.Direction =impulse;
            //direction -= impulse;
            energy -= 1;
            otherShip.energy -= 1;
            otherShip.force -= impulse;
            force += impulse;
        }

        public void Blow()
        {
            //cmdr.score += 10;
            //if (ship.Owner == ShipOwner.Pirate)
            //{
            //    cmdr.credits += 10;
            //}
            //particlesManager.StartNew(ship.Location);

            Sounds.Sound.Play("Thunder_5");



        }

        public void FlyToPoint(Vector3 targetPoint)
        {
            Vector3 dest = (targetPoint - this.location);
            Vector3 result = new Vector3(Vector3.Dot(dest, this.Right),
            Vector3.Dot(dest, this.Up),
            Vector3.Dot(dest, this.Direction));

            direction.Normalize();

            float updownRot;
            float leftrightRot;
            AnglesFromDirection(direction - result, out updownRot, out leftrightRot);

            this.Direction = result;

            this.Rotations = new Vector3((leftrightRot) / 100f, updownRot / 50f, 0);
        }

        private void AnglesFromDirection(Vector3 direction, out float updownAngle, out float leftrightAngle)
        {
            Vector3 floorProjection = new Vector3(direction.X, 0, direction.Z);
            float directionLenght = floorProjection.Length();

            updownAngle = (float)Math.Atan2(direction.Y, directionLenght);
            leftrightAngle = -(float)Math.Atan2(direction.X, -direction.Z);
        }
    }
}
